#pragma once
#include <vector>
#include "common.hpp"
#include "macro.hpp"
#include "abstract.hpp"

namespace MyRpc
{
    class JsonMessage : public BaseMessage
    {
    public:
        using ptr = std::shared_ptr<JsonMessage>;
        virtual bool serialize(std::string& body) override
        {
            return JSON::serialize(_body, body);
        }

        virtual bool unserialize(const std::string& body) override
        {
            return JSON::deserialize(body, _body);
        }
        virtual bool check() = 0;
    protected:
        Json::Value _body;
    };

    class JsonRequest : public JsonMessage
    {

    };

    // 在不同的类中实现不同的check方法
    class RpcRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<RpcRequest>;
        virtual bool check() override
        {
            // 检查method是否合适 还有 参数是否合适
            if(_body[KEY_METHOD].isString() == false || _body[KEY_METHOD].isNull() == true)
            {
                LOG(DEBUGLEVEL, "请求的method出现问题!");
                return false;
            }
            if(_body[KEY_PARAMS].isNull() == true)
            {
                LOG(DEBUGLEVEL, "请求的parameters出现问题!");
                return false;
            }
            return true;
        }

        std::string method() { return _body[KEY_METHOD].asString(); }
        void setMethod(const std::string& mtype) { _body[KEY_METHOD] = mtype; }
        Json::Value parameters() { return _body[KEY_PARAMS]; }
        void setParameters(const Json::Value& para) { _body[KEY_PARAMS] = para; }

        // MType method() { return _mtype; }
        // void setMethod(const MType& mtype) { _mtype = mtype; }
        // Json::Value parameters() { return _parameters; }
        // void setParameters(const Json::Value& para) { _parameters = para; }
        
    // private:
    //     MType _mtype;
    //     Json::Value _parameters;
    };

    class TopicRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<TopicRequest>;
        virtual bool check() override
        {
            // 检查method是否合适 还有 参数是否合适
            if(_body[KEY_TOPIC_KEY].isString() == false || _body[KEY_TOPIC_KEY].isNull() == true)
            {
                LOG(DEBUGLEVEL, "请求的topic_key字段出现出现问题!");
                return false;
            }
            if(_body[KEY_OPTYPE].isInt() == false || _body[KEY_OPTYPE].isNull() == true)
            {
                LOG(DEBUGLEVEL, "请求的topic_optype操作方式出现问题!");
                return false;
            }
            // 如果是publish功能 就得有msg数据进行pulish
            if(_body[KEY_OPTYPE].asInt() == (int)TopicRequestOpType::TOPIC_PUBLISH)
            {
                if(_body[KEY_TOPIC_MSG].isNull() || _body[KEY_TOPIC_MSG].isString() == false)
                {
                    LOG(DEBUGLEVEL, "请求主题publish字段消息出现错误!");
                    return false;
                }
                else
                    return true;
            }
            return true;
        }

        TopicRequestOpType topicRequsetOpty() { return (TopicRequestOpType)_body[KEY_OPTYPE].asInt(); }
        void setTopicRequsetOpty(const TopicRequestOpType& topicOp) { _body[KEY_OPTYPE] = (int)topicOp; }
        std::string msg() { return _body[KEY_TOPIC_MSG].asString(); }
        void setMsg(const std::string& msg) { _body[KEY_TOPIC_MSG] = msg; }        
        std::string key() { return _body[KEY_TOPIC_KEY].asString(); }
        void setKey(const std::string& key) { _body[KEY_TOPIC_KEY] = key; }

        // TopicRequestOpType topicRequsetOpty() { return _topicOp; }
        // void setTopicRequsetOpty(const TopicRequestOpType& topicOp) { _topicOp = topicOp; }
        // std::string msg() { return _msg; }
        // void setMsg(const std::string& msg) { _msg = msg; }        
        // std::string key() { return _key; }
        // void setKey(const std::string& key) { _key = key; }

    // private:
    //     std::string _key;
    //     TopicRequestOpType _topicOp;
    //     std::string _msg;
    };

    using Addr = std::pair<std::string, int>;
    class ServiceRequest : public JsonRequest
    {
    public:
        using ptr = std::shared_ptr<ServiceRequest>;
        virtual bool check() override
        {
            if(_body[KEY_OPTYPE].isNull() == true || _body[KEY_OPTYPE].isInt() == false)
            {
                LOG(DEBUGLEVEL, "服务请求optype出现问题!");
                return false; 
            }
            // 走到这块说明 有操作方式
            // 如果操作方式是发现主机服务 这里没有method方式 也没有主机
            if(_body[KEY_OPTYPE].asInt() != (int)ServiceRequestOpType::SERVICE_DISCOVERY)
            {
                if(_body[KEY_METHOD].isNull() == true || _body[KEY_METHOD].isString() == false)
                {
                    LOG(DEBUGLEVEL, "服务请求method出现错误!");
                    return false;
                }
                if(_body[KEY_HOST][KEY_HOST_IP].isNull() == true || _body[KEY_HOST][KEY_HOST_IP].isString() == false)
                {
                    LOG(DEBUGLEVEL, "服务请求host中ip出现问题!");
                    return false;
                }
                if(_body[KEY_HOST][KEY_HOST_PORT].isNull() == true || _body[KEY_HOST][KEY_HOST_PORT].isInt() == false)
                {
                    LOG(DEBUGLEVEL, "服务请求host中port出现问题!");
                    return false;
                }
            }

            return true;        
        }
        // ServiceRequestOpType optype() { return _op; }
        // void setOptype(const ServiceRequestOpType& op) { _op = op; }
        // MType mType() { return _mtype; }
        // void setMType(const MType& mtype) { _mtype = mtype; }

        ServiceRequestOpType optype() { return (ServiceRequestOpType)_body[KEY_OPTYPE].asInt(); }
        void setOptype(const ServiceRequestOpType& op) { _body[KEY_OPTYPE] = (int)op; }
        std::string method() { return _body[KEY_METHOD].asString(); }
        void setMethod(const std::string& mtype) { _body[KEY_METHOD] = mtype; }

        Addr host() 
        {
            Addr addr;
            addr.first = _body[KEY_HOST][KEY_HOST_IP].asString();
            addr.second = _body[KEY_HOST][KEY_HOST_PORT].asInt();
            return addr;
        }
        void setHost(const Addr& addr) 
        {
            Json::Value host;
            host[KEY_HOST_IP] = addr.first;
            host[KEY_HOST_PORT] = addr.second;
            // _host = host;
            _body[KEY_HOST] = host;
        }
    // private:
    //     ServiceRequestOpType _op;
    //     MType _mtype;
    //     Json::Value _host;
    };

    class JsonResponse : public JsonMessage
    {
    public:
        using ptr = std::shared_ptr<JsonResponse>;
        virtual bool check()
        {

        }
        void setRcode(const RCode& rcode) { _body[KEY_RCODE] = (int)rcode; }
        RCode rcode() { return (RCode)_body[KEY_RCODE].asInt(); }
    };

    class RpcResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<RpcResponse>;
        virtual bool check() override
        {
            if(_body[KEY_RCODE].isNull() == true || _body[KEY_RCODE].isInt() == false)
            {
                LOG(DEBUGLEVEL, "RpcResponse的RCode出现问题!");
                return false;
            }
            if(_body[KEY_RESULT].isNull() == true)
            {
                LOG(DEBUGLEVEL, "RpcResponse的结果出现问题!");
                return false;
            }
            return true;
        }

        Json::Value result() { return _body[KEY_RESULT]; }
        void setResult(const Json::Value& result) { _body[KEY_RESULT] = result; }
    };

    class TopicResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<TopicResponse>;
        virtual bool check() override
        {
            if(_body[KEY_RCODE].isNull() == true || _body[KEY_RCODE].isInt() == false)
            {
                LOG(DEBUGLEVEL, "TopicResponse的RCode出现问题!");
                return false;
            }
            return true;
        }
    };

    class ServiceResponse : public JsonResponse
    {
    public:
        using ptr = std::shared_ptr<ServiceResponse>;
        virtual bool check() override
        {
            if(_body[KEY_RCODE].isNull() == true || _body[KEY_RCODE].isInt() == false)
            {
                LOG(DEBUGLEVEL, "ServiceResponse的RCode出现问题!");
                return false;
            }
            if(_body[KEY_OPTYPE].isNull() == true || _body[KEY_OPTYPE].isInt() == false)
            {
                LOG(DEBUGLEVEL, "ServiceResponse的optype出现问题!");
                return false;
            }
            // 如果是服务发现应答
            if(_body[KEY_OPTYPE].asInt() == (int)ServiceRequestOpType::SERVICE_DISCOVERY)
            {
                if(_body[KEY_METHOD].isNull() == true || _body[KEY_METHOD].isString() == false)
                {
                    LOG(DEBUGLEVEL, "ServiceResponse的Method出现问题!");
                    return false;
                }
                if(_body[KEY_HOST].isNull() == true || _body[KEY_HOST].isArray() == false)
                {
                    LOG(DEBUGLEVEL, "ServiceResponse的Host出现问题!");
                    return false;
                }
            }
            return true;
        }
        void setOptype(const ServiceRequestOpType& op) { _body[KEY_OPTYPE] = (int)op; }
        ServiceRequestOpType optype() { return (ServiceRequestOpType)_body[KEY_OPTYPE].asInt(); }
        std::string method() { return _body[KEY_METHOD].asString(); }
        void setMethod(const std::string& mtype) { _body[KEY_METHOD] = mtype; }

        std::vector<Addr> hosts()
        {
            std::vector<Addr> addrs;
            int size = _body[KEY_HOST].size();
            for(int i = 0; i < size; i++)
            {
                Addr addr;
                addr.first = _body[KEY_HOST][i][KEY_HOST_IP].asString();
                addr.second = _body[KEY_HOST][i][KEY_HOST_PORT].asInt();
                addrs.push_back(addr);
            }
            return addrs;
        }

        void setHosts(const std::vector<Addr>& addrs)
        {
            for(auto& e : addrs)
            {
                Json::Value addr;
                addr[KEY_HOST_IP] = e.first;
                addr[KEY_HOST_PORT] = e.second;
                _body[KEY_HOST].append(addr);
            }
        }
    };

    // 创建生产对象的工厂
    class MessageFactory
    {
    public:
        // 根据请求类型转化需要生产的对象
        static BaseMessage::ptr create(const MType& mtype)
        {
            switch(mtype)
            {
                case MType::REQ_RPC : return std::make_shared<RpcRequest>();
                case MType::REQ_TOPIC : return std::make_shared<TopicRequest>();
                case MType::REQ_SERVICE : return std::make_shared<ServiceRequest>();
                case MType::RSP_RPC : return std::make_shared<RpcResponse>();
                case MType::RSP_TOPIC : return std::make_shared<TopicResponse>();
                case MType::RSP_SERVICE : return std::make_shared<ServiceResponse>();
            }
            return BaseMessage::ptr();
        }

        template<typename T, typename ...Args>
        static std::shared_ptr<T> create(Args&& ...args)
        {
            return std::make_shared<T>(std::forward<Args>(args)...);
        }
    };
}